home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / sys5 / iscwmpst.z / iscwmpst / tcp / src / slip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-10  |  5.5 KB  |  260 lines

  1. /* @(#) $Header: slip.c,v 1.7 91/05/09 07:38:52 deyke Exp $ */
  2.  
  3. /* SLIP (Serial Line IP) encapsulation and control routines.
  4.  * Copyright 1991 Phil Karn
  5.  *
  6.  * Van Jacobsen header compression hooks added by Katie Stevens, UC Davis
  7.  *
  8.  *      - Feb 1991      Bill_Simpson@um.cc.umich.edu
  9.  *                      reflect changes to header compression calls
  10.  *                      revise status display
  11.  */
  12. #include <stdio.h>
  13. #include "global.h"
  14. #include "config.h"
  15. #include "mbuf.h"
  16. #include "iface.h"
  17. #include "ip.h"
  18. /* #include "slhc.h" */
  19. #include "asy.h"
  20. #include "slip.h"
  21. #include "trace.h"
  22.  
  23. static struct mbuf *slip_decode __ARGS((struct slip *sp,int c));
  24. static struct mbuf *slip_encode __ARGS((struct mbuf *bp));
  25.  
  26. /* Slip level control structure */
  27. struct slip Slip[ASY_MAX];
  28.  
  29. /* Send routine for point-to-point slip */
  30. int
  31. slip_send(bp,iface,gateway,prec,del,tput,rel)
  32. struct mbuf *bp;        /* Buffer to send */
  33. struct iface *iface;    /* Pointer to interface control block */
  34. int32 gateway;          /* Ignored (SLIP is point-to-point) */
  35. int prec;
  36. int del;
  37. int tput;
  38. int rel;
  39. {
  40. #ifdef VJCOMPRESS
  41.     register struct slip *sp;
  42.     int type;
  43. #endif
  44.     if(iface == NULLIF){
  45.         free_p(bp);
  46.         return -1;
  47.     }
  48. #ifdef VJCOMPRESS
  49.     sp = &Slip[iface->xdev];
  50.     if (sp->escaped & SLIP_VJCOMPR) {
  51.         /* Attempt IP/ICP header compression */
  52.         type = slhc_compress(sp->slcomp,&bp,TRUE);
  53.         bp->data[0] |= type;
  54.     }
  55. #endif
  56.     return (*iface->raw)(iface,bp);
  57. }
  58. /* Send a raw slip frame */
  59. int
  60. slip_raw(iface,bp)
  61. struct iface *iface;
  62. struct mbuf *bp;
  63. {
  64.     struct mbuf *bp1;
  65.  
  66.     dump(iface,IF_TRACE_OUT,Slip[iface->xdev].type,bp);
  67.     iface->rawsndcnt++;
  68.     iface->lastsent = secclock();
  69.     if((bp1 = slip_encode(bp)) == NULLBUF){
  70.         free_p(bp);
  71.         return -1;
  72.     }
  73.     if (iface->trace & IF_TRACE_RAW)
  74.         raw_dump(iface,-1,bp1);
  75.     return Slip[iface->xdev].send(iface->dev,bp1);
  76. }
  77. /* Encode a packet in SLIP format */
  78. static
  79. struct mbuf *
  80. slip_encode(bp)
  81. struct mbuf *bp;
  82. {
  83.     struct mbuf *lbp;       /* Mbuf containing line-ready packet */
  84.     register char *cp;
  85.     int c;
  86.  
  87.     /* Allocate output mbuf that's twice as long as the packet.
  88.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  89.      */
  90.     lbp = alloc_mbuf((int16)(2*len_p(bp) + 2));
  91.     if(lbp == NULLBUF){
  92.         /* No space; drop */
  93.         free_p(bp);
  94.         return NULLBUF;
  95.     }
  96.     cp = lbp->data;
  97.  
  98.     /* Flush out any line garbage */
  99.     *cp++ = FR_END;
  100.  
  101.     /* Copy input to output, escaping special characters */
  102.     while((c = PULLCHAR(&bp)) != -1){
  103.         switch(c){
  104.         case FR_ESC:
  105.             *cp++ = FR_ESC;
  106.             *cp++ = T_FR_ESC;
  107.             break;
  108.         case FR_END:
  109.             *cp++ = FR_ESC;
  110.             *cp++ = T_FR_END;
  111.             break;
  112.         default:
  113.             *cp++ = c;
  114.         }
  115.     }
  116.     *cp++ = FR_END;
  117.     lbp->cnt = cp - lbp->data;
  118.     return lbp;
  119. }
  120. /* Process incoming bytes in SLIP format
  121.  * When a buffer is complete, return it; otherwise NULLBUF
  122.  */
  123. static
  124. struct mbuf *
  125. slip_decode(sp,c)
  126. register struct slip *sp;
  127. char c;         /* Incoming character */
  128. {
  129.     struct mbuf *bp;
  130.  
  131.     switch(uchar(c)){
  132.     case FR_END:
  133.         bp = sp->rbp_head;
  134.         sp->rbp_head = NULLBUF;
  135.         sp->rcnt = 0;
  136.         return bp;      /* Will be NULLBUF if empty frame */
  137.     case FR_ESC:
  138.         sp->escaped |= SLIP_FLAG;
  139.         return NULLBUF;
  140.     }
  141.     if(sp->escaped & SLIP_FLAG){
  142.         /* Translate 2-char escape sequence back to original char */
  143.         sp->escaped &= ~SLIP_FLAG;
  144.         switch(uchar(c)){
  145.         case T_FR_ESC:
  146.             c = FR_ESC;
  147.             break;
  148.         case T_FR_END:
  149.             c = FR_END;
  150.             break;
  151.         default:
  152.             sp->errors++;
  153.             break;
  154.         }
  155.     }
  156.     /* We reach here with a character for the buffer;
  157.      * make sure there's space for it
  158.      */
  159.     if(sp->rbp_head == NULLBUF){
  160.         /* Allocate first mbuf for new packet */
  161.         if((sp->rbp_tail = sp->rbp_head = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  162.             return NULLBUF; /* No memory, drop */
  163.         sp->rcp = sp->rbp_head->data;
  164.     } else if(sp->rbp_tail->cnt == SLIP_ALLOC){
  165.         /* Current mbuf is full; link in another */
  166.         if((sp->rbp_tail->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  167.             /* No memory, drop whole thing */
  168.             free_p(sp->rbp_head);
  169.             sp->rbp_head = NULLBUF;
  170.             sp->rcnt = 0;
  171.             return NULLBUF;
  172.         }
  173.         sp->rbp_tail = sp->rbp_tail->next;
  174.         sp->rcp = sp->rbp_tail->data;
  175.     }
  176.     /* Store the character, increment fragment and total
  177.      * byte counts
  178.      */
  179.     *sp->rcp++ = c;
  180.     sp->rbp_tail->cnt++;
  181.     sp->rcnt++;
  182.     return NULLBUF;
  183. }
  184. /* Process SLIP line input */
  185. void
  186. asy_rx(iface)
  187. struct iface *iface;
  188. {
  189.  
  190.     char *cp,buf[4096];
  191.     int cnt,xdev;
  192.     struct mbuf *bp;
  193.     register struct slip *sp;
  194.     int cdev;
  195.  
  196.     xdev = iface->xdev;
  197.     sp = &Slip[xdev];
  198.     cdev = sp->iface->dev;
  199.  
  200.     cnt = (*sp->get)(cdev,cp=buf,sizeof(buf));
  201.     while(--cnt >= 0){
  202.         if((bp = slip_decode(sp,*cp++)) == NULLBUF)
  203.             continue;       /* More to come */
  204.  
  205. #ifdef VJCOMPRESS
  206.         if (sp->iface->trace & IF_TRACE_RAW)
  207.             raw_dump(sp->iface,IF_TRACE_IN,bp);
  208.  
  209.         if (sp->escaped & SLIP_VJCOMPR) {
  210.             if ((c = bp->data[0]) & SL_TYPE_COMPRESSED_TCP) {
  211.                 if ( slhc_uncompress(sp->slcomp, &bp) <= 0 ) {
  212.                     free_p(bp);
  213.                     sp->errors++;
  214.                     continue;
  215.                 }
  216.             } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
  217.                 bp->data[0] &= 0x4f;
  218.                 if ( slhc_remember(sp->slcomp, &bp) <= 0 ) {
  219.                     free_p(bp);
  220.                     sp->errors++;
  221.                     continue;
  222.                 }
  223.             }
  224.         }
  225. #endif
  226.         if ( net_route( sp->iface, sp->type, bp ) != 0 ) {
  227.             free_p(bp);
  228.         }
  229.     }
  230. /*      free_p(bp); */
  231. }
  232.  
  233. /* Show serial line status */
  234. int
  235. slip_status(iface)
  236. struct iface *iface;
  237. {
  238.     struct slip *sp;
  239.  
  240.     if (iface->xdev > SLIP_MAX)
  241.         /* Must not be a SLIP device */
  242.         return 1;
  243.  
  244.     sp = &Slip[iface->xdev];
  245.     if (sp->iface != iface)
  246.         /* Must not be a SLIP device */
  247.         return 1;
  248.  
  249.     tprintf("  IN:\t%lu pkts\n", iface->rawrecvcnt);
  250. #ifdef VJCOMPRESS
  251.     slhc_i_status(sp->slcomp);
  252. #endif
  253.     tprintf("  OUT:\t%lu pkts\n", iface->rawsndcnt);
  254. #ifdef VJCOMPRESS
  255.     slhc_o_status(sp->slcomp);
  256. #endif
  257.     return 0;
  258. }
  259.  
  260.